package com.zmc.mallgateway.filter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zmc.common.constant.AuthConstants;
import com.zmc.common.constant.Constants;
import com.zmc.common.enums.ErrorCodeEnum;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * @Author：zmc
 * @Date：2024/12/26 12:47
 * 全局拦截器
 */

@Component
public class TokenValidFilter implements GlobalFilter {

    public static final Logger log = LoggerFactory.getLogger(TokenValidFilter.class);

    public static final String PICTURE_VISIT_PATH_PREFIX = "/admin/profile";


    @Value("${white.url}")
    private List<String> whiteUrlList;


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        if (whiteUrlList.contains(path) || path.startsWith(PICTURE_VISIT_PATH_PREFIX)){
            return chain.filter(exchange);
        }
        //校验token
        HttpHeaders headers = request.getHeaders();
        List<String> authorization = headers.get(AuthConstants.JWT_HEADER);
        if (!CollectionUtils.isEmpty(authorization)){
            String token = authorization.get(0);
            if (StringUtils.hasText(token) && token.startsWith(Constants.TOKEN_PREFIX)){
                token = token.replace(Constants.TOKEN_PREFIX, "");
                //验证token是否可正确（防止伪造）
                try{
                    Object uuid = Jwts.parser()
                            .setSigningKey(AuthConstants.JWT_SECRET)
                            .parseClaimsJws(token)
                            .getBody().get(Constants.LOGIN_USER_KEY);
                    if (!Objects.isNull(uuid)) {
                        return chain.filter(exchange);
                    }
                }catch (Exception exception){
                    log.error("TokenValidFilter：解析token异常,需重新登录", exception);
                }
            }
        }
        //校验失败，返回401
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().set("content-type","application/json;charset=utf-8");
        HashMap<String, Object> map = new HashMap<>(4);
        //返回401
        map.put("code", ErrorCodeEnum.TOKEN_EXPIRE_EXCEPTION.getCode());
        map.put("msg",ErrorCodeEnum.TOKEN_EXPIRE_EXCEPTION.getMsg());
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = new byte[0];
        try {
            bytes = objectMapper.writeValueAsBytes(map);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        DataBuffer wrap = response.bufferFactory().wrap(bytes);
        return response.writeWith(Mono.just(wrap));
    }


}
